home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 3
/
Amiga Format CD03 (1996-07-04)(Future Publishing)(GB)(Track 1 of 6)[!][issue 1996-08].iso
/
comms
/
netsoftware
/
nethandler.lha
/
NetHandler
/
dnetlib.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-09-16
|
11KB
|
478 lines
/*
* DNETLIB.C
*
* DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved.
*
* Library Interface for DNET.
*/
#define NOEXT
#define NETCOMMON
#include "dnet.h"
#include "netcomm.h"
#include "proto.h"
static struct DChannel *MakeChannel U_ARGS((IOR *, char *));
static void DeleteChannel U_ARGS((struct DChannel *));
static void FixSignal U_ARGS((struct DChannel *));
#define NAMELEN sizeof("DNET.PORT.XXXXX")
#define NAMEPAT "DNET.PORT.%ld"
PORT *DListen(portnum)
uword portnum;
{
PORT *port;
char *ptr;
port = NULL;
ptr = AllocMem(NAMELEN, MEMF_PUBLIC); /* memory the the name */
sprintf(ptr, NAMEPAT, portnum);
Forbid(); /* task-atomic operation */
if (FindPort(ptr) || !(port = CreatePort(ptr,0)))
FreeMem(ptr, NAMELEN);
Permit();
return(port);
}
void
DUnListen(lisport)
PORT *lisport;
{
register char *ptr;
ptr = lisport->mp_Node.ln_Name;
if (lisport)
{
Forbid(); /* task-atomic operation */
while (DNAAccept(lisport)); /* remove all pending requests */
DeletePort(lisport); /* gone! */
Permit();
FreeMem(ptr, NAMELEN);
}
}
/*
* DAccept()
*
* Note: This call will work even if called by a task which does not
* own the listen port.
*/
PORT *
DAccept(lisport)
PORT *lisport;
{
register IOR *ior;
register struct DChannel * chan;
BUG(("DAccept: Entry, port %lx\n", lisport))
chan = NULL;
while (!chan && (ior = (IOR *)GetMsg(lisport))) {
switch(ior->io_Command) {
case DNCMD_SOPEN:
BUG(("DAccept: SOPEN command\n"))
chan = MakeChannel(ior, NULL);
break;
default:
BUG(("DAccept: Unrecognized command '%d'\n", ior->io_Command))
ior->io_Error = 1;
break;
}
BUG(("DAccept: Replying\n"))
ReplyMsg(&ior->io_Message);
}
BUG(("DAccept: After while loop\n"))
if (lisport->mp_MsgList.lh_Head != (NODE *)&lisport->mp_MsgList.lh_Tail)
SetSignal(1 << lisport->mp_SigBit, 1 << lisport->mp_SigBit);
return(chan ? &chan->port : NULL);
}
/*
* Refuse a connection
*/
DNAAccept(lisport)
PORT *lisport;
{
IOR *ior;
if (ior = (IOR *)GetMsg(lisport)) {
ior->io_Error = 1;
ReplyMsg(&ior->io_Message);
}
if (lisport->mp_MsgList.lh_Head != (NODE *)&lisport->mp_MsgList.lh_Tail)
SetSignal(1 << lisport->mp_SigBit, 1 << lisport->mp_SigBit);
return(ior != NULL);
}
void DPri(chan, pri)
struct DChannel * chan;
int pri;
{
}
PORT *
DOpen(host, portnum, txpri, rxpri)
char *host;
char txpri, rxpri;
uword portnum;
{
IOR ior;
struct DChannel *chan;
if (!host)
host = "0";
chan = MakeChannel(&ior, host);
if (rxpri > 126)
rxpri = 126;
if (rxpri < -127)
rxpri = -127;
if (txpri > 126)
txpri = 126;
if (txpri < -127)
txpri = -127;
if (chan->dnetport) {
ior.io_Command = DNCMD_OPEN;
ior.io_Unit = (void *)portnum;
ior.io_Offset = (long)chan;
ior.io_Message.mn_ReplyPort = &chan->port;
ior.io_Message.mn_Node.ln_Pri = txpri;
ior.io_Message.mn_Node.ln_Name= (char *)rxpri;
PutMsg(chan->dnetport, &ior.io_Message);
WaitMsg(&ior);
if (ior.io_Error == 0) {
chan->chan = (long)ior.io_Unit;
FixSignal(chan);
return(&chan->port);
}
}
DeleteChannel(chan);
return(NULL);
}
DNRead(chan, buf, bytes)
struct DChannel * chan;
char *buf;
int bytes;
{
register IOR *ior;
int len;
long n;
len = 0;
if (chan->eof)
return(-1);
while (bytes && ((ior = (IOR *)
RemHead((struct List *)&chan->rdylist)) ||
(ior = (IOR *)GetMsg(&chan->port)))) {
if (ior->io_Message.mn_Node.ln_Type == NT_REPLYMSG)
{
if (!chan->queued)
{
BUG(("DNRead: Software Error"));
}
else
--chan->queued;
if (ior->io_Length)
FreeMem((char *)ior->io_Data, (long)ior->io_Length);
FreeMem((char *)ior, (long)sizeof(IOR));
continue;
}
switch(ior->io_Command)
{
case DNCMD_CLOSE:
case DNCMD_EOF:
chan->eof = 1;
ReplyMsg(&ior->io_Message);
break;
case DNCMD_WRITE:
n = ior->io_Length - ior->io_Actual;
if (n <= bytes)
{
memcpy(buf, ((char *)ior->io_Data) + ior->io_Actual, n);
bytes -= n;
len += n;
buf += n;
ReplyMsg(&ior->io_Message);
}
else
{
memcpy(buf, (char *)ior->io_Data + ior->io_Actual, bytes);
len += bytes;
ior->io_Actual += bytes;
bytes = 0;
Forbid(); /* DNET device is a task, no need to Disable() */
ior->io_Message.mn_Node.ln_Type = NT_MESSAGE;
AddHead(&chan->port.mp_MsgList, (struct Node *)ior);
Permit();
}
break;
default:
ior->io_Error = 1;
ReplyMsg(&ior->io_Message);
}
}
FixSignal(chan);
if (chan->eof)
SetSignal(1 << chan->port.mp_SigBit, 1 << chan->port.mp_SigBit);
return(len);
}
int DRead(chan, buf, bytes)
char *buf;
struct DChannel * chan;
int bytes;
{
long len;
long n;
len = 0;
if (chan->eof)
{
BUG(("****DNET EOF!!!\n"));
return(-1);
}
while (bytes)
{
WaitPort(&chan->port);
n = DNRead(chan, buf, bytes);
len += n;
if (n < 0) break;
buf += n;
bytes -= n;
if (chan->eof) break;
}
return(len);
}
void DQueue(chan, n)
struct DChannel * chan;
int n;
{
chan->qlen = n;
}
DWrite(chan, buf, bytes)
struct DChannel * chan;
char *buf;
int bytes;
{
IOR tmpior;
IOR *ior;
int error;
error = bytes;
if (chan->qlen)
{
if (WaitQueue(chan, NULL) >= 0)
{
ior = (IOR *)AllocMem(sizeof(IOR), MEMF_CLEAR|MEMF_PUBLIC);
ior->io_Command = DNCMD_WRITE;
ior->io_Unit = (void *)chan->chan;
ior->io_Offset = (long)chan;
ior->io_Message.mn_ReplyPort = &chan->port;
ior->io_Data = (APTR)AllocMem(bytes, MEMF_PUBLIC);
ior->io_Length = bytes;
memcpy((char *)ior->io_Data, buf, (int)bytes);
PutMsg(chan->dnetport, &ior->io_Message);
++chan->queued;
}
else
{
error = -1;
}
}
else
{
tmpior.io_Command = DNCMD_WRITE;
tmpior.io_Unit = (void *)chan->chan;
tmpior.io_Offset = (long)chan;
tmpior.io_Message.mn_ReplyPort = &chan->port;
tmpior.io_Data = (APTR)buf;
tmpior.io_Length = bytes;
PutMsg(chan->dnetport, &tmpior.io_Message);
WaitMsg(&tmpior);
if (tmpior.io_Error)
{
error = -1;
BUG(("*****DWrite: io_Error %d\n", tmpior.io_Error));
BUGGETC
}
}
FixSignal(chan);
return(error);
}
void DEof(chan)
struct DChannel * chan;
{
IOR ior;
ior.io_Command = DNCMD_EOF;
ior.io_Unit = (void *)chan->chan;
ior.io_Offset = (long)chan;
ior.io_Message.mn_ReplyPort = &chan->port;
PutMsg(chan->dnetport, &ior.io_Message);
WaitMsg(&ior);
FixSignal(chan);
}
void DIoctl(chan, cmd, val, aux)
struct DChannel * chan;
ubyte cmd;
uword val;
ubyte aux;
{
IOR ior;
ior.io_Command = DNCMD_IOCTL;
ior.io_Unit = (void *)chan->chan;
ior.io_Offset = (long)chan;
ior.io_Message.mn_ReplyPort = &chan->port;
ior.io_Data = (APTR)(long)((val<<16)|(aux<<8)|cmd);
PutMsg(chan->dnetport, &ior.io_Message);
WaitMsg(&ior);
FixSignal(chan);
}
int DQuit(host)
char *host;
{
IOR ior;
char buf[sizeof(DNETPORTNAME)+32];
PORT *replyport;
PORT *dnetport;
if (!host)
host = "0";
sprintf(buf, "%s%s", DNETPORTNAME, host);
if (dnetport = FindPort(buf)) {
replyport = CreatePort(NULL, 0);
ior.io_Command = DNCMD_QUIT;
ior.io_Unit = 0;
ior.io_Offset = 0;
ior.io_Message.mn_ReplyPort = replyport;
PutMsg(dnetport, &ior.io_Message);
WaitMsg(&ior);
DeletePort(replyport);
}
return(dnetport != NULL);
}
void DClose(chan)
struct DChannel * chan;
{
IOR ior;
IOR *io;
BUG(("DClose: Enter\n"))
ior.io_Command = DNCMD_CLOSE;
ior.io_Unit = (void *)chan->chan;
ior.io_Offset = (long)chan;
ior.io_Message.mn_ReplyPort = &chan->port;
PutMsg(chan->dnetport, &ior.io_Message);
++chan->queued;
chan->qlen = 0;
WaitQueue(chan, &ior);
while ((io = (IOR *)RemHead((struct List *)&chan->rdylist)) ||
(io = (IOR *)GetMsg(&chan->port))) {
io->io_Error = 1;
ReplyMsg(&io->io_Message);
}
DeleteChannel(chan);
}
void WaitMsg(ior)
IOR *ior;
{
while (ior->io_Message.mn_Node.ln_Type != NT_REPLYMSG)
Wait(1 << ior->io_Message.mn_ReplyPort->mp_SigBit);
Forbid();
Remove((struct Node *)ior);
Permit();
}
int WaitQueue(chan, skipior)
struct DChannel * chan;
IOR *skipior;
{
register IOR *io;
short error;
error = 0;
while (chan->queued > chan->qlen) { /* until done */
WaitPort(&chan->port); /* something */
io = (IOR *)GetMsg(&chan->port);
if (io->io_Message.mn_Node.ln_Type == NT_REPLYMSG) {
if (error == 0)
error = io->io_Error;
if (io != skipior) {
if (io->io_Length)
FreeMem((char *)io->io_Data, io->io_Length);
FreeMem((char *)io, sizeof(IOR));
}
--chan->queued;
} else {
AddTail(&chan->rdylist, (struct Node *)io);
}
}
return(error);
}
static struct DChannel *MakeChannel(ior, host)
register IOR *ior;
char *host;
{
struct DChannel * chan;
char buf[sizeof(DNETPORTNAME)+32];
BUG(("MakeChannel: Entry\n"))
chan = (struct DChannel *)AllocMem(sizeof(struct DChannel),
MEMF_PUBLIC|MEMF_CLEAR);
/* Name, Pri */
chan->port.mp_Node.ln_Type = NT_MSGPORT;
chan->port.mp_SigBit = AllocSignal(-1);
chan->port.mp_SigTask = FindTask(NULL);
NewList(&chan->port.mp_MsgList);
NewList(&chan->rdylist);
chan->chan = (long)ior->io_Unit;
ior->io_Offset = (long)chan;
if (host) {
sprintf(buf, "%s%s", DNETPORTNAME, host);
ior->io_Message.mn_ReplyPort = FindPort(buf);
}
chan->dnetport = ior->io_Message.mn_ReplyPort;
return(chan);
}
static void
DeleteChannel(chan)
struct DChannel * chan;
{
FreeSignal(chan->port.mp_SigBit);
FreeMem((char *)chan, (long)sizeof(struct DChannel));
}
static void
FixSignal(chan)
register struct DChannel * chan;
{
if (chan->port.mp_MsgList.lh_Head !=
(NODE *)&chan->port.mp_MsgList.lh_Tail ||
chan->rdylist.lh_Head != (NODE *)&chan->rdylist.lh_Tail)
SetSignal(1 << chan->port.mp_SigBit, 1 << chan->port.mp_SigBit);
}